<?php

namespace App\Models;

use App\Http\Controllers\Controller;
use Exception;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;

/**
 * 用户预约表
 * Class ReservationApplyModel
 * @package app\common\model
 */
class ReservationApply extends BaseModel
{

    use HasFactory;

    const CREATED_AT = 'create_time';
    const UPDATED_AT = 'change_time';

    public $table = 'reservation_apply';

    /**
     * 关联用户数据
     */
    public function conUser()
    {
        return $this->hasOne(UserInfo::class, 'id', 'user_id');
    }

    /**
     * 关联排班表
     */
    public function conSchedule()
    {
        return $this->hasOne(ReservationSchedule::class, 'id', 'schedule_id');
    }

    /**
     * 关联特殊排班表
     */
    public function conSpecialSchedule()
    {
        return $this->hasOne(ReservationSpecialSchedule::class, 'id', 'schedule_id');
    }

    /*关联预约信息*/
    public function conReservation()
    {
        return $this->hasOne(Reservation::class, 'id', 'reservation_id');
    }

    /**
     * 判断当前未过期已预约次数
     * @param user_id   用户id
     * @param reservation_id  预约id
     */
    public function getReservationNotOutNumber($user_id, $account_id, $reservation_id, $node = null)
    {
        $number = $this->where('reservation_id', $reservation_id)
            ->where(function ($query) use ($user_id, $account_id) {
                if ($user_id) {
                    $query->where('user_id', $user_id);
                } else {
                    $query->where('account_id', $account_id);
                }
            })
            ->where(function ($query) use ($node) {
                if ($node == 7) {
                    $query->whereIn('status', [1, 3, 6]);
                } else {
                    $query->whereIn('status', [1, 3]);
                }
            })->count();
        return $number;
    }

    /**
     * 获取未审核预约个数
     * @param act_id 活动id  空表示全部
     */
    public function getUncheckedReservationNumber($reservation_id = null)
    {
        return $this->where(function ($query) use ($reservation_id) {
            if ($reservation_id) {
                $query->where('reservation_id', $reservation_id);
            }
        })->where('status', 3)->count();
    }

    /**
     * 获取预约数量
     * @param reservation_id int 预约id
     * @param status int 用于筛选用户列表  预约状态   1.已通过  3待审核，4已拒绝  5 已过期 , 6 已签到
     */
    public function getMakeNumber($reservation_id = '', $status = [1, 3, 5, 6, 7])
    {
        $res = $this->where('reservation_id', $reservation_id)
            ->where(function ($query) use ($status) {
                if ($status) {
                    $query->whereIn('status', $status);
                }
            })
            ->count();
        return $res;
    }

    /**
     * 预约申请列表
     * @param reservation_id int 预约id
     * @param limit int 分页大小
     * @param keywords string 搜索关键词
     * @param start_date date 搜索开始时间
     * @param end_date date 搜索结束时间
     * @param status int 用于筛选用户列表  预约状态   1.已通过  3待审核，4已拒绝  5 已过期 , 6 已签到 7 已签退
     * @param is_violate int 是否违规  1正常 2违规 默认1
     * @param make_way int 预约方式   1  前台自主预约  2 管理员手动预约
     */
    public function lists($reservation_id = '', $user_id = '', $status = [], $is_violate = '', $keywords = '', $start_date = '', $end_date = '', $make_way = null, $limit = 10)
    {
        $res = $this->from($this->getTable() . ' as a')
            ->leftJoin('user_info as b', 'a.user_id', '=', 'b.id')
            ->leftJoin('user_wechat_info as w', 'b.wechat_id', '=', 'w.id')
            ->leftJoin('manage as m', 'a.manage_id', '=', 'm.id')
            ->select(
                'a.id',
                'a.user_id',
                'a.account_id',
                'a.number',
                'a.reservation_id',
                'a.schedule_id',
                'a.schedule_type',
                'a.seat_id',
                //    'reservation_violate_num as violate_num',
                'a.create_time',
                'a.make_time',
                'a.expire_time',
                'a.status',
                'a.reason',
                'a.change_time',
                'a.is_violate',
                'a.violate_reason',
                'a.tel',
                'a.sign_time',
                'a.sign_end_time',
                'a.return_expire_time',
                'a.unit',
                'a.remark',
                'a.id_card',
                'a.img',
                'a.sex',
                'a.age',
                'a.tel',
                'a.reader_id',
                'a.username',
                'a.serial_number',
                'a.make_way',
                'w.head_img',
                'w.nickname',
                'm.' . Manage::$manage_name . ' as manage_name',
                DB::raw('if(status = 3,0,1) as sort')
            )
            ->with(['conSchedule' => function ($query) {
                $query->select('id', 'week', 'start_time', 'end_time');
            }, 'conSpecialSchedule' => function ($query) {
                $query->select('id', 'date', 'start_time', 'end_time');
            }])
            ->where(function ($query) use ($keywords) {
                $query->where('a.tel', 'like', "%$keywords%")
                    ->orWhere('a.id_card', 'like', "%$keywords%")
                    ->orWhere('a.unit', 'like', "%$keywords%")
                    ->orWhere('a.serial_number', 'like', "%$keywords%")
                    ->orWhere('a.reader_id', 'like', "%$keywords%")
                    ->orWhere('w.nickname', 'like', "%$keywords%");
            })
            ->where(function ($query) use ($reservation_id, $user_id, $status, $is_violate, $start_date, $end_date, $make_way) {
                if ($start_date && $end_date) {
                    $query->whereBetween('make_time', [$start_date, $end_date]);
                }
                if ($status) {
                    $status = !is_array($status) ? explode(',', $status) : $status;
                    $query->whereIn('status', $status);
                }
                if ($reservation_id) {
                    $query->where('reservation_id', $reservation_id);
                }
                if ($user_id) {
                    $query->where('user_id', $user_id);
                }
                if ($is_violate) {
                    $query->where('is_violate', $is_violate);
                }
                if ($make_way) {
                    $query->where('make_way', $make_way);
                }
            })
            ->whereIn('status', [1, 3, 4, 5, 6, 7])
            ->orderBy('sort')
            ->orderByDesc('id')
            ->paginate($limit)
            ->toArray();


        foreach ($res['data'] as $key => $val) {
            $reservation_info = Reservation::where('id', $val['reservation_id'])->first();
            if ($reservation_info['node'] != 7) {
                if ($val['schedule_type'] == 2) {
                    $res['data'][$key]['con_schedule'] = $val['con_special_schedule'];
                    $week = date('w', strtotime($val['con_special_schedule']['date']));
                    $res['data'][$key]['con_schedule']['week'] = get_week_name($week);
                    unset($res['data'][$key]['con_special_schedule']);
                } else {
                    $res['data'][$key]['con_schedule']['week'] = get_week_name($val['con_schedule']['week']);
                }
            } else {
                $res['data'][$key]['serial_number'] = ($val['status'] == 1 ||  $val['status'] == 6 ||  $val['status'] == 7) ? $val['serial_number'] : '';
            }
            if ($val['seat_id']) {
                $reservationSeatModel = new ReservationSeat();
                $max_seat_number = $reservationSeatModel->maxSeatNumber($val['reservation_id']);
                $seat_number = $reservationSeatModel->where('id', $val['seat_id'])->value('number');
                $serial_prefix = $reservation_info['serial_prefix'];
                $end_seat = strlen($max_seat_number);
                $res['data'][$key]['seat_number'] = $reservationSeatModel->getSeatNumber($serial_prefix, $end_seat, $seat_number);
            } else {
                $res['data'][$key]['seat_number'] = null;
            }
            //判断是否可以取消
            $is_can_cancel = $this->isCanCancel($reservation_info, $val);
            $res['data'][$key]['is_can_cancel'] = $is_can_cancel === true ? true : false;

            //重置用户填写信息
            if ($val['account_id']) {
                $user_account_info = UserLibraryInfo::where('id', $val['account_id'])->first();
                if ($user_account_info) {
                    $res['data'][$key]['id_card'] = $val['id_card'] ? $val['id_card'] : $user_account_info['id_card'];
                    $res['data'][$key]['sex'] = $val['sex'] ? $val['sex'] : $user_account_info['sex'];
                    $res['data'][$key]['tel'] = $val['tel'] ? $val['tel'] : $user_account_info['tel'];
                    $res['data'][$key]['age'] = $val['age'] ? $val['age'] : ($user_account_info['id_card'] ?  get_user_age_by_id_card($user_account_info['id_card']) : '');
                    $res['data'][$key]['reader_id'] = $val['reader_id'] ? $val['reader_id'] : $user_account_info['account'];
                    $res['data'][$key]['username'] = $val['username'] ? $val['username'] : $user_account_info['username'];
                }
            }
        }
        return $res;
    }


    /**
     * 判断当前时间段是否已被预约完毕
     * @param $reservation_id  商品guid
     * @param $schedule_id  时间段id
     * @param $schedule_type 预约类型 1正常  2特殊日期
     * @param $make_time  预约日期
     * @param $kind  物品种类   1 单一物品 （人物默认是单一） 2 多物品 (到馆默认是多个，但是一人只能预约一个)  到馆和座位是多物品预约
     * @param $number  多物品数量
     * @param $seat_id  座位id
     * @param $status  状态
     */
    public function makeStatus($reservation_id, $schedule_id, $schedule_type, $make_time, $kind, $number, $seat_id = null, $status = [1, 3, 6], $node = '')
    {
        $make_time = date('Y-m-d', strtotime($make_time));
        $status = $this->where('reservation_id', $reservation_id)
            ->select(DB::raw('sum(number) as number'))
            ->where(function ($query) use ($node, $schedule_id, $schedule_type, $make_time) {
                if ($node != 7) {
                    if ($schedule_id) {
                        $query->where('schedule_id', $schedule_id);
                    }
                    if ($schedule_type) {
                        $query->where('schedule_type', $schedule_type);
                    }
                    if ($make_time) {
                        $query->where('make_time', $make_time);
                    }
                }
            })
            ->where(function ($query) use ($status) {
                if ($status) {
                    $query->whereIn('status', $status);
                }
            })->where(function ($query) use ($seat_id) {
                if ($seat_id) {
                    $query->where('seat_id', $seat_id); //座位预约独有
                }
            })->first();
        if (empty($status['number'])) {
            return false;
        }

        //座位号存在，就是单一物品
        if ($kind == 1 || $seat_id) {
            // return 1;  //单一物品只要预约就是预约完毕，返回剩余一个数量
            return 0;  //单一物品只要预约就是预约完毕，返回剩余0个数量  2021.703 修改
        } else {
            return $number - $status['number']; //返回剩余数量
        }
    }

    /**
     * 判断当前时间段是否已被预约完毕
     * @param $reservation_id  商品guid
     * @param $schedule_id  时间段id
     * @param $schedule_type 预约类型 1正常  2特殊日期
     * @param $make_time  预约日期
     * @param $kind  物品种类   1 单一物品 （人物默认是单一） 2 多物品 (到馆默认是多个，但是一人只能预约一个)  到馆和座位是多物品预约
     * @param $number  多物品数量
     * @param $seat_id  座位id
     * @param $status  状态
     */
    public function getMakeStatus($reservation_id, $schedule_id, $schedule_type, $make_time, $seat_id = null, $status = [1, 3, 6], $node = '')
    {
        $make_time = date('Y-m-d', strtotime($make_time));
        $status = $this->where('reservation_id', $reservation_id)
            ->select('status')
            ->where(function ($query) use ($node, $schedule_id, $schedule_type, $make_time) {
                if ($node != 7) {
                    if ($schedule_id) {
                        $query->where('schedule_id', $schedule_id);
                    }
                    if ($schedule_type) {
                        $query->where('schedule_type', $schedule_type);
                    }
                    if ($make_time) {
                        $query->where('make_time', $make_time);
                    }
                }
            })
            ->where(function ($query) use ($status) {
                if ($status) {
                    $query->whereIn('status', $status);
                }
            })->where(function ($query) use ($seat_id) {
                if ($seat_id) {
                    $query->where('seat_id', $seat_id); //座位预约独有
                }
            })->first();
        return $status;
    }


    /**
     * 判断当前时间段自己是否已预约
     * @param $user_id   用户id
     * @param $account_id   读者证号id  主要针对后台管理员预约
     * @param $reservation_id  商品id
     * @param $schedule_id  时间段id
     * @param $schedule_type  预约类型 1正常 2特殊时间
     * @param $make_time  预约日期
     * @param $node  int 分类  0全部  1  人物    2  物品    3 教室   4 展览预约    5 到馆预约 6 座位预约  7 储物柜预约
     */
    public function selfMakeStatus($user_id, $account_id, $reservation_id, $schedule_id, $schedule_type, $make_time, $seat_id = null, $status = [1, 3, 6], $node = '')
    {
        $make_time = date('Y-m-d', strtotime($make_time));

        $status = $this->where('reservation_id', $reservation_id)
            ->select('id', 'number', 'change_time')
            ->where(function ($query) use ($user_id, $account_id) {
                // if ($user_id) {
                //     $query->where('user_id', $user_id);
                // } else {
                //     $query->where('account_id', $account_id);
                // }

                if ($user_id) {
                    $query->where('user_id', $user_id);
                }
                if ($account_id) {
                    $query->where('account_id', $account_id);
                }
            })
            ->where(function ($query) use ($node, $schedule_id, $schedule_type, $make_time) {
                if ($node != 7) {
                    if ($schedule_id) {
                        $query->where('schedule_id', $schedule_id);
                    }
                    if ($schedule_type) {
                        $query->where('schedule_type', $schedule_type);
                    }
                    if ($make_time) {
                        $query->where('make_time', $make_time);
                    }
                }
            })
            ->where(function ($query) use ($status) {
                if ($status) {
                    $query->whereIn('status', $status);
                }
            })->where(function ($query) use ($seat_id) {
                if ($seat_id) {
                    $query->where('seat_id', $seat_id); //座位预约独有
                }
            })->orderByDesc('id')
            ->first();
        return $status ? $status->toArray() : null;
    }

    /**
     * 判断当前时间里自己是否有，有效预约
     * @param $user_id   用户id
     * @param $reservation_id  商品id
     * @param $schedule_id  时间段id
     * @param $schedule_type  预约类型 1正常 2特殊时间
     * @param $make_time  预约日期 默认当天
     */
    public function nowTimeMakeInfo($user_id, $reservation_id, $schedule_id, $schedule_type, $seat_id = null, $status = [1, 3, 6], $make_time = null, $node = null)
    {
        $res = $this->where('reservation_id', $reservation_id)
            ->where('user_id', $user_id)
            ->where(function ($query) use ($node, $schedule_id, $schedule_type, $make_time) {
                if ($node != 7) {
                    if ($schedule_id) {
                        $query->where('schedule_id', $schedule_id);
                    }
                    if ($schedule_type) {
                        $query->where('schedule_type', $schedule_type);
                    }
                    if ($make_time) {
                        $query->where('make_time', $make_time); //预约时间，默认是当天
                    }
                }
            })
            ->where(function ($query) use ($status, $seat_id, $make_time) {
                if ($status) {
                    $query->whereIn('status', $status);
                }
                if ($seat_id) {
                    $query->where('seat_id', $seat_id); //座位预约独有
                }
            })->first();
        if (empty($res)) {
            return [];
        }
        // if ($res['status'] == 1 && $res['expire_time'] < date('Y-m-d H:i:s')) {
        //     return []; //已过期，返回[]
        // }

        return $res;
    }


    /**
     * 判断当前时间段所有有效预约
     * @param $user_id   用户id
     * @param $reservation_id  预约id
     * @param $schedule_id  时间段id
     * @param $make_time  预约日期
     */
    public function validMake($reservation_id = null, $schedule_id = null, $schedule_type = null, $make_time = null, $seat_id = null, $status = [1, 3, 6], $node = null)
    {
        $make_time = date('Y-m-d', strtotime($make_time));

        $res = $this->select('number', 'user_id', 'seat_id')
            ->where(function ($query) use ($node, $reservation_id, $schedule_id, $schedule_type, $make_time, $status, $seat_id) {
                if ($node != 7) {
                    if ($schedule_id) {
                        $query->where('schedule_id', $schedule_id);
                    }
                    if ($schedule_type) {
                        $query->where('schedule_type', $schedule_type);
                    }
                    if ($make_time) {
                        $query->where('make_time', $make_time);
                    }
                }
                if ($reservation_id) {
                    $query->where('reservation_id', $reservation_id);
                }
                if ($status) {
                    $query->whereIn('status', $status);
                }
                if ($seat_id) {
                    $query->where('seat_id', $seat_id); //座位预约独有
                }
            })->get()->toArray();

        return $res;
    }


    /**
     * 获取预约信息
     * @param $make_id   预约id
     */
    public function getMakeInfo($make_id)
    {
        $res = $this->from('reservation_apply as a')->select(
            'a.reservation_id',
            'a.schedule_type',
            'a.make_time',
            'a.remark',
            'a.status',
            'a.reason',
            'a.number',
            'a.create_time',
            '(case when a.schedule_type=2 then p.start_time else s.start_time end ) as start_time',
            '(case when a.schedule_type=2 then p.end_time else s.end_time end ) as end_time'
        )
            ->leftJoin('reservation_schedule as s', 's.id', '=', 'a.schedule_id')
            ->leftJoin('reservation_special_schedule t', 't.id = a.schedule_id')
            ->where('a.id', $make_id)
            // ->where('s.is_del' , 1)
            ->first();
        return $res;
    }

    /**
     * 根据条件获取座位信息
     * @param  $reservation_id 预约id
     * @param  $seat_id 座位id  数组
     * @param  $date  某个时间的预约
     * @param  $symbol  符号，是大于这个时间，还是等于这个时间 '>' , '='
     * @param  $status  预约状态  数组
     * @param  $schedule_type  排版类型 1正常排班 2特殊日期排
     * @param  $schedule_id  排版id 查询具体的排版信息
     * @param  $node  int 分类  0全部  1  人物    2  物品    3 教室   4 展览预约    5 到馆预约 6 座位预约  7 储物柜预约
     */
    public function getApplyInfo($reservation_id = '', $seat_id = [], $date = '', $symbol = '>', $status = [], $schedule_type = null, $schedule_id = null, $node = null)
    {
        return $this->where(function ($query) use ($node, $reservation_id, $seat_id, $date, $symbol, $status, $schedule_type, $schedule_id) {
            if ($reservation_id) {
                $query->where('reservation_id', $reservation_id);
            }
            if ($seat_id) {
                $query->whereIn('seat_id', $seat_id);
            }
            if ($status) {
                $query->whereIn('status', $status);
            }
            if ($node != 7) {
                if ($date) {
                    $query->where('make_time', $symbol, $date);
                }
                if ($schedule_type) {
                    $query->where('schedule_type', $schedule_type);
                }
                if ($schedule_id) {
                    $query->where('schedule_id', $schedule_id);
                }
            }
        })->get()
            ->toArray();
    }

    public static function getApplyObj()
    {
        return new self();
    }

    /**
     * 审核通过 和 拒绝
     * @param id int 申请id
     * @param status int 状态  1.已通过 3.已拒绝
     */
    public function agreeAndRefused($id, $status, $reason = null)
    {
        $res = $this->where('id', $id)->first();
        if (!$res) {
            throw new Exception("参数传递错误");
        }

        if ($res->status != 3) {
            throw new Exception("不处于未审核状态");
        }

        $res->status = $status;
        if ($status == 4) {
            $res->reason = $reason;
        }
        $res->manage_id = request()->manage_id;
        $res->save();
        return $res;
    }

    //获取
    public function getConSchedule($con_schedule, $make_time)
    {
        if (!empty($con_schedule)) {
            $reservation_time = $make_time . '
                    ' . $con_schedule['week'] . '
                    ' . $con_schedule['start_time'] . ' 至 ' . $con_schedule['end_time'];
        } else {
            $reservation_time = $make_time;
        }
        return $reservation_time;
    }

    /*座位预约状态*/
    public function getStatusName($status, $node = null)
    {
        switch ($status) {
            case 1:
                return '已通过';
                break;
            case 2:
                return '已取消';
                break;
            case 3:
                return '待审核';
                break;
            case 4:
                return '已拒绝';
                break;
            case ($status == 5 && $node != 7):
                return '已过期';
                break;
            case ($status == 5 && $node == 7):
                return '过期未领取';
                break;
            case ($status == 6 && $node != 7):
                return '已签到';
                break;
            case ($status == 6 && $node == 7):
                return '已领取';
                break;
            case ($status == 7 && $node != 7):
                return '已签退';
                break;
            case ($status == 7 && $node == 7):
                return '已归还';
                break;
            default:
                return '未知状态';
                break;
        }
    }

    /**
     * 整理schedule时间以及是否可预约
     * @param  $user_id 用户id
     * @param  $reservation_data 预约的值
     * @param  $data 要处理的schedule原数据
     * @param  $cur_date 当前日期
     * @param  $schedule_type int 查询类型 1 普通排版，2特殊日期排版
     */
    public function getScheduleDetail($user_id, $reservation_info, $data, $cur_date, $schedule_type)
    {
        if ($reservation_info['node'] == 6) {
            //座位预约，需要重置下座位数量
            $reservation_info['number'] = ReservationSeat::where('reservation_id', $reservation_info['id'])->where('is_del', 1)->where('is_play', 1)->count();
        }

        $temp_temp['schedule_type'] = $schedule_type;
        $temp_temp['schedule_id'] = $data['id'];
        $temp_temp['stage'] = get_hour_minute_by_time($data['start_time']) . "-" . get_hour_minute_by_time($data['end_time']);

        $temp_temp['is_make'] = true; //都是不可预约状态
        $temp_temp['is_self_make'] = false; //是否自己预约
        if (date('Y-m-d') == $cur_date && date('H:i:s', strtotime("+30 min")) > $data['end_time']) {

            $apply_number = $this->where('schedule_id', $data['id'])->where('reservation_id', $reservation_info['id'])->where('schedule_type', $schedule_type)->where('status', [1, 3, 6])->count();
            $temp_temp['surplus_number'] = $reservation_info['number'] - $apply_number;
        } else {
            //获取此时间段是否已被预约完毕
            $status = $this->makeStatus($reservation_info['id'], $data['id'], $schedule_type, $cur_date, $reservation_info['kind'], $reservation_info['number']);
            if ($status === false || $status > 0) {
                //可以被预约
                if (!empty($user_id)) {
                    //判断自己是否已预约
                    $selfStatus = $this->selfMakeStatus($user_id, null, $reservation_info['id'], $data['id'], $schedule_type, $cur_date);
                    if ($selfStatus) {
                        $temp_temp['is_make'] = true; //已被预约，不能继续预约
                        $temp_temp['is_self_make'] = true; //已被预约，不能继续预约
                    } else {
                        $temp_temp['is_make'] = false; //没有被预约，可以继续预约
                    }
                } else {
                    $temp_temp['is_make'] = false; //没有被预约，可以继续预约
                }
            }

            if ($temp_temp['is_make'] === false) {
                //判断剩余个数
                if ($reservation_info['kind'] == 2) {
                    $temp_temp['surplus_number'] = $status === false ? $reservation_info['number'] : $status; //返回剩余个数
                } else {
                    $temp_temp['surplus_number'] = 1; //返回剩余个数为 1
                }
            } else {
                $temp_temp['surplus_number'] = $status === false ? $reservation_info['number'] : $status;; //返回剩余个数为 0
            }
        }
        return $temp_temp;
    }

    /**
     * 我的预约列表
     * @param  $authorrization ：用户 token   必选
     * @param  $node  int 分类  0全部  1  人物    2  物品    3 教室   4 展览预约    5 到馆预约 6 座位预约
     * @param  $status  预约状态   1.已通过（待使用）  2.已取消，3 待审核（待审核）  4已拒绝 ,5 已过期 , 6 已签到（已使用）  7 结束打卡（增对座位预约）（已使用）
     *                  状态可分为 3类  全部  待审核3   待使用1  已使用 67  其余展示在全部里面
     * @param  $page  页数  默认为 1
     * @param  $limit  分页限制  默认为 10
     */
    public function myMakeList($user_id, $node = null, $status = null, $limit = 10)
    {
        $data = $this->from('reservation as r')
            ->select(
                'a.seat_id',
                'a.make_time',
                'a.status',
                'a.number as make_number',
                'a.create_time',
                'a.id as apply_id',
                'a.schedule_id',
                'a.schedule_type',
                'a.change_time',
                'a.expire_time',
                'a.sign_time',
                'a.sign_end_time',
                'a.return_expire_time', //应归还时间
                'a.serial_number', //预约编号
                'a.reason', //拒绝理由

                'a.tel as make_tel',
                'a.unit as make_unit',
                'a.id_card',
                'a.sex',
                'a.age',
                'a.reader_id',
                'a.img as make_img',
                'a.username',
                'a.remark',

                'r.id',
                'r.is_real',   //是否需要用户真实信息 1需要 2不需要 默认2
                'r.real_info',
                'r.node',
                'r.serial_prefix',
                'r.is_cancel',
                'r.is_approval',
                //  'r.kind',
                'r.name',
                'r.img',
                'r.intro',
                'r.type_tag',
                'r.number',
                'r.province',
                'r.city',
                'r.district',
                'r.address',
                'r.tel',
                'r.cancel_end_time',
                's.week',
                's.start_time as normal_start_time',
                's.end_time as normal_end_time',
                't.date',
                't.start_time as special_start_time',
                't.end_time as special_end_time'
            )
            ->join('reservation_apply as a', 'a.reservation_id', '=', 'r.id')
            ->leftJoin('reservation_schedule as s', 's.id', '=', 'a.schedule_id')
            ->leftJoin('reservation_special_schedule as t', 't.id', '=', 'a.schedule_id')
            ->where(function ($query) use ($node, $status) {
                if ($node) {
                    $query->where('r.node', $node);
                }
                if ($status) {
                    $status = !is_array($status) ? explode(',', $status) : $status;
                    $query->whereIn('a.status', $status);
                }
            })
            ->where('r.is_del', 1)
            ->where('r.is_play', 1)
            // ->where('s.is_del' , 1)
            ->where('a.user_id', $user_id)
            ->orderByDesc('a.make_time') //以预约的时间来排序
            ->orderByDesc('a.id') //在以预约的实际时间来排序
            ->paginate($limit)
            ->toArray();

        $reservationSeatModel = new ReservationSeat();
        $reservationModel = new Reservation();
        $controllerObj = new Controller();
        $real_info_arr = $reservationModel->getReservationApplyParam(); //获取所有的数据

        $node_name = $reservationModel->reservationNode();

        $node_name = array_column($node_name, 'name', 'node');
        foreach ($data['data'] as $key => &$val) {
            $data['data'][$key]['type_tag'] = !empty($val['type_tag']) ? explode("|", $val['type_tag']) : [];
            $data['data'][$key]['intro'] = strip_tags($val['intro']);
            $data['data'][$key]['real_info'] = $controllerObj->getRealInfoArray($val['real_info'], $real_info_arr);

            $data['data'][$key]['node_name'] = $node_name[$val['node']];

            $data['data'][$key]['make_info']['schedule_id'] = $val['schedule_id'];
            $data['data'][$key]['make_info']['schedule_type'] = $val['schedule_type'];
            $data['data'][$key]['make_info']['id'] = $val['apply_id'];
            $data['data'][$key]['make_info']['make_time'] = date("Y/m/d", strtotime($val['make_time']));

            if ($val['node'] != 7) {
                $week = $val['schedule_type'] == 2 ? date('w', strtotime($val['date'])) : $val['week'];
            } else {
                $week = date('w', strtotime($val['make_time']));
            }
            $data['data'][$key]['make_info']['week'] = get_week_name($week);

            $data['data'][$key]['make_info']['serial_number'] = $val['serial_number'];
            $data['data'][$key]['make_info']['status'] = $val['status'];
            $data['data'][$key]['make_info']['number'] = $val['make_number'];
            $data['data'][$key]['make_info']['create_time'] = $val['create_time'];
            $data['data'][$key]['make_info']['start_time'] = $val['schedule_type'] == 1 ? $val['normal_start_time'] : $val['special_start_time'];
            $data['data'][$key]['make_info']['end_time'] = $val['schedule_type'] == 1 ? $val['normal_end_time'] : $val['special_end_time'];
            $data['data'][$key]['make_info']['change_time'] = $val['change_time'];
            $data['data'][$key]['make_info']['expire_time'] = $val['expire_time'];
            $data['data'][$key]['make_info']['sign_time'] = $val['sign_time'];
            $data['data'][$key]['make_info']['sign_end_time'] = $val['sign_end_time'];
            $data['data'][$key]['make_info']['return_expire_time'] = $val['return_expire_time']; //应归还时间
            $data['data'][$key]['make_info']['reason'] = $val['reason']; //拒绝理由

            $data['data'][$key]['make_info']['tel'] = $val['make_tel'];
            $data['data'][$key]['make_info']['unit'] = $val['make_unit'];
            $data['data'][$key]['make_info']['id_card'] = $val['id_card'];
            $data['data'][$key]['make_info']['sex'] = $val['sex'];
            $data['data'][$key]['make_info']['age'] = $val['age'];
            $data['data'][$key]['make_info']['reader_id'] = $val['reader_id'];
            $data['data'][$key]['make_info']['img'] = $val['make_img'];
            $data['data'][$key]['make_info']['username'] = $val['username'];
            $data['data'][$key]['make_info']['remark'] = $val['remark'];

            // $data['data'][$key]['make_info']['sign_end_time'] = $val['sign_end_time'];

            if ($val['seat_id']) {
                $seat_name = $reservationSeatModel->where('id', $val['seat_id'])->value('number');
                $max_seat_number = $reservationSeatModel->maxSeatNumber($val['id']);
                $end_seat = strlen($max_seat_number);
                $data['data'][$key]['make_info']['seat_name'] = $reservationSeatModel->getSeatNumber($val['serial_prefix'], $end_seat, $seat_name);
            } else {
                $data['data'][$key]['make_info']['seat_name'] = '';
            }

            //判断是否可以取消
            $is_can_cancel = $this->isCanCancel($val, $data['data'][$key]['make_info']);
            $data['data'][$key]['make_info']['is_can_cancel'] = $is_can_cancel === true ? true : false;

            //是否能显示签到二维码
            if ($val['node'] != 7) {
                $is_can_show_qr = $this->isCanShowQr($user_id, null,  ['status' => $val['status'], 'make_time' => $val['make_time'], 'reservation_id' => $val['id']]);
                $data['data'][$key]['make_info']['is_can_show_qr'] = $is_can_show_qr === true ? true : false;
            } else {
                $data['data'][$key]['make_info']['is_can_show_qr'] = false; //储物柜预约不能出示二维码
            }

            $data['data'][$key]['make_info']['lib_name'] = config('other.lib_name');

            unset($val['reservation_type'], $val['make_time'], $val['remark'], $val['status'], $val['make_number'], $val['create_time'], $val['start_time'], $val['end_time'], $val['schedule_id']);
            unset($val['schedule_type'], $val['normal_start_time'], $val['special_start_time'], $val['normal_end_time'], $val['special_end_time']);
            unset($val['serial_prefix'], $val['is_cancel'], $val['is_approval'], $val['serial_number'], $val['reason']);
        }
        return $data;
    }

    /**
     * 判断是否可以取消
     */
    public function isCanCancel($reservation_info, $make_info)
    {
        if ($reservation_info['is_cancel'] == 2) {
            return '该预约不允许取消';
        }

        if ($reservation_info['is_approval'] == 1) {
            if ($make_info['status'] != 3) {
                return '当前状态不能取消预约';
            }
        } else {
            if ($reservation_info['is_cancel'] == 2) {
                return '当前状态不能取消预约';
            } else {
                if ($make_info['status'] != 1) {
                    return '当前状态不能取消预约';
                }
            }
        }

        if ($reservation_info['node'] != 7) {
            $scheduleModel = $make_info['schedule_type'] == 2 ? new ReservationSpecialSchedule() : new ReservationSchedule();
            $schedule_info = $scheduleModel->where('id', $make_info['schedule_id'])->first();

            if (strtotime($make_info['make_time'] . ' ' . $schedule_info['start_time']) < strtotime($make_info['create_time'])) {
                //预约开始才预约
                if ($reservation_info['cancel_end_time'] && (time() - $reservation_info['cancel_end_time'] * 60 > strtotime($make_info['create_time']))) {
                    return '已超过预约可取消时间';
                }
            } else {
                //预约开始前预约
                if ($reservation_info['cancel_end_time'] && (time() + $reservation_info['cancel_end_time'] * 60 > strtotime($make_info['make_time'] . ' ' . $schedule_info['start_time']))) {
                    return '已超过预约可取消时间';
                }
            }
        } else {
            //预约开始前预约
            if ($reservation_info['cancel_end_time'] && (time() + $reservation_info['cancel_end_time'] * 60 > strtotime($make_info['expire_time']))) {
                return '已超过预约可取消时间';
            }
        }
        return true;
    }


    /**
     * 预约数据
     * @param $reservation_id_arr 预约id  数组
     * @param $way 返回数据方式 1 数量  2 数组
     */
    public function makeReservationData($user_id = null, $node = null, $reservation_id_arr = null, $status = null, $start_time = null, $end_time = null, $make_time = null, $schedule_id = null, $schedule_type = null, $way = 1)
    {
        $res = $this->from('reservation_apply as a')
            ->join('reservation as r', 'r.id', '=', 'a.reservation_id')
            ->where(function ($query) use ($node, $user_id, $reservation_id_arr, $status, $start_time, $end_time, $schedule_id, $schedule_type, $make_time) {
                if ($node) {
                    $query->where('r.node', $node);
                }
                if ($user_id) {
                    $query->where('a.user_id', $user_id);
                }
                if ($status) {
                    $status = !is_array($status) ? explode(',', $status) : $status;
                    $query->whereIn('a.status', $status);
                }
                if ($start_time && $end_time) {
                    $query->whereBetween('a.create_time', [$start_time, $end_time]);
                }
                if ($reservation_id_arr) {
                    $query->whereIn('r.id', $reservation_id_arr);
                }
                if ($node != 7) {
                    if ($schedule_id) {
                        $query->where('a.schedule_id', $schedule_id);
                    }
                    if ($schedule_type) {
                        $query->where('a.schedule_type', $schedule_type);
                    }
                    if ($make_time) {
                        $query->where('a.make_time', $make_time);
                    }
                }
            })
            ->where('r.is_del', 1);
        if ($way == 1) {
            $res = $res->count();
        } else {
            $res = $res->get()->toArray();
        }
        return $res;
    }

    /**
     * 获取当前预约储物柜数量
     */
    public function getCabinetApplyNumber($id)
    {
        $number = $this->whereIn('status', [1, 3, 6])->where('reservation_id', $id)->count();
        return $number;
    }


    /**
     * 获取当前座位空置数量
     * @param $reservation_id_arr 预约id  数组
     * @param $number 总座位数量
     */
    public function emptySeatNumber($reservation_id_arr, $number)
    {
        $week = date("w");
        $weeks = $week ? $week : 7;
        $reservationScheduleModel = new ReservationSchedule();
        $reservationModel = new Reservation();
        $total_make_number = 0;
        foreach ($reservation_id_arr as $key => $val) {
            list($schedule_type, $reservation_schedule) = $reservationScheduleModel->getReservationSchedule($val, $weeks);
            if ($schedule_type === false) {
                continue;
            }
            //查询当前预约数量
            $node = $reservationModel->where('id', $val)->value('node');
            $make_number = $this->makeReservationData(null, $node, [$val], [1, 3, 6], null, null, date('Y-m-d'), $reservation_schedule['id'], $schedule_type);
            $total_make_number += $make_number;
        }
        return $number - $total_make_number;
    }

    /**
     * 获取当前座位空置数据
     * @param $reservation_id_arr 预约id 数组格式
     */
    public function makeSeatData($reservation_id_arr)
    {
        //获取所有座位
        $reservationSeatModel = new ReservationSeat();

        $week = date("w");
        $weeks = $week ? $week : 7;
        $reservationScheduleModel = new ReservationSchedule();
        $reservationModel = new Reservation();
        $data = [];
        $i = 0;
        foreach ($reservation_id_arr as $key => $val) {
            list($schedule_type, $reservation_schedule) = $reservationScheduleModel->getReservationSchedule($val, $weeks);
            if ($schedule_type === false) {
                continue;
            }
            //查询当前预约数量
            $reservation_info = $reservationModel->select('name', 'serial_prefix', 'node')->where('id', $val)->first();
            $make_info = $this->makeReservationData(null, $reservation_info['node'], [$val], [1, 3, 6], null, null, date('Y-m-d'), $reservation_schedule['id'], $schedule_type, 2);
            $seat_id_arr = array_column($make_info, 'seat_id');
            $serial_prefix = $reservation_info['serial_prefix'];
            $max_seat_number = $reservationSeatModel->maxSeatNumber($val, 1);
            $end_seat = strlen($max_seat_number);

            $reservation_seat_info = $reservationSeatModel->select('id', 'number')
                ->where('reservation_id', $val)
                ->where('is_play', 1)
                ->where('is_del', 1)
                ->get()
                ->toArray();

            if (empty($reservation_seat_info)) {
                continue;
            }
            foreach ($reservation_seat_info as $k => $v) {
                $data[$i]['content'][$k]['seat_name'] = $reservationSeatModel->getSeatNumber($serial_prefix, $end_seat, $v['number']);
                if ($make_info && in_array($v['id'], $seat_id_arr)) {
                    $data[$i]['content'][$k]['status'] = 1; //已预约
                } else {
                    $data[$i]['content'][$k]['status'] = 2; //空闲
                }
            }
            $data[$i]['name'] = $reservation_info['name'];
            $i++;
        }
        if (empty($data[0]['name'])) {
            $data[$i]['name'] = '预约';
        }
        if (empty($data[1]['name'])) {
            $data[$i]['name'] = '预约';
        }
        //手动增加数据
        $i1 = !empty($data[0]['content']) ? count($data[0]['content']) + 1 : 1;
        for ($i = $i1; $i <= 10; $i++) {
            $data[0]['content'][$i - 1]['status'] = 1; //已预约
            $data[0]['content'][$i - 1]['seat_name'] = 'A' . $i; //已预约
        }

        $i2 = !empty($data[1]['content']) ? count($data[1]['content']) + 1 : 1;
        for ($i = $i2; $i <= 6; $i++) {
            $data[1]['content'][$i - 1]['status'] = 1; //已预约
            $data[1]['content'][$i - 1]['seat_name'] = 'A' . $i; //已预约
        }

        for ($i = 1; $i <= 12; $i++) {
            $data[2]['content'][$i - 1]['status'] = 1; //已预约
            $data[2]['content'][$i - 1]['seat_name'] = 'C' . $i; //已预约
        }
        $data[2]['name'] = '预约';
        return $data;
    }

    /**
     * 判断是否可以显示二维码
     * @param $apply_info 预约信息
     * @param $apply_id 预约id
     * @param $user_id 用户id
     */
    public function isCanShowQr($user_id, $apply_id, $apply_info = null)
    {
        if (empty($apply_id) && empty($apply_info)) {
            return '预约信息不存在';
        }
        if (empty($apply_info)) {
            $apply_info = $this->where('id', $apply_id)->where('user_id', $user_id)->first();
        }
        if (empty($apply_info)) {
            return '预约信息不存在';
        }

        if ($apply_info['make_time'] != date('Y-m-d')) {
            return '当前时间不能出示二维码';
        }

        // 预约是否存在
        $res_info = Reservation::where("id", $apply_info['reservation_id'])->where("is_del", 1)->where("is_play", 1)->first();

        if ($res_info['node'] == 7) {
            //只有拿到了钥匙才能展示，因为未拿到钥匙前，管理员需要分配钥匙，所以不能出示
            if ($apply_info['status'] != 6) {
                return '当前状态不能出示二维码';
            }
        } else {
            //已通过和已签到可以出示，其余不可以出示,有自动过期，所以不用考虑过期时间等
            if ($apply_info['status'] != 1 && $apply_info['status'] != 6) {
                return '当前状态不能出示二维码';
            }
        }

        if (empty($res_info)) return "预约不存在或已被删除";
        if ($res_info['sign_way'] == 2) return '请使用扫码功能进行扫码操作';

        return true;
    }
}
